﻿using System;

namespace LxCFD
{
    public class MGContactCreator
    {
        public QueueTool QueueTool_O;
        public QueueTool QueueTool_N;
        public MGCellTemp[] contactTempCells;

        IProvideContactTopology fineContact;

        int[] InOCoarseCell;
        int[] InNCoarseCell;

        int tempCellsStart;

        MGContact coarseContact;
        public MGContact CreateMGContact(IProvideContactTopology fineContact, MGZone OZone, MGZone NZone, IndexNumber OIndex, IndexNumber NIndex)
        {
            this.fineContact = fineContact;
            int count = fineContact.GetInnerIndex().FaceIDs.GetCount();
            InOCoarseCell = new int[count];
            InNCoarseCell = new int[count];
            for (int i1 = 0; i1 < count; i1++)
            {
                InOCoarseCell[i1] = -1;
                InNCoarseCell[i1] = -1;//防止出错了不知道
            }
            coarseContact = new MGContact();
            coarseContact.O_Zone = OZone;
            coarseContact.N_Zone = NZone;
            coarseContact.O_Cells = OZone.Cells;
            coarseContact.N_Cells = NZone.Cells;
            coarseContact.O_Faces = OZone.Faces;
            coarseContact.N_Faces = NZone.Faces;
            coarseContact.O_Index = OIndex;
            coarseContact.N_Index = NIndex;
            makeFlag();
            addContactFaceToStorage();
            splitContactCoarseFaceFromStorage();
            checkTopology();
            InOCoarseCell = null;
            InNCoarseCell = null;
            contactTempCells = null;
            return coarseContact;
        }
        private void makeFlag()
        {
            IndexRecorder oCellIDs = coarseContact.O_Index.CellIDs;
            IndexRecorder nCellIDs = coarseContact.N_Index.CellIDs;
            contactTempCells = new MGCellTemp[oCellIDs.GetCount()];
            for (int i1 = 0; i1 < contactTempCells.Length; ++i1)
            {
                contactTempCells[i1] = new MGCellTemp();
            }
            tempCellsStart = oCellIDs.Start;
            for (int i1 = oCellIDs.Start; i1 <= oCellIDs.End; ++i1)
            {
                foreach (var c in coarseContact.O_Cells[i1].FineCells)
                {
                    foreach (var ffid in fineContact.GetOZoneCellOFaces(c))
                    {
                        InOCoarseCell[ffid] = i1;
                    }
                }
            }
            for (int i1 = nCellIDs.Start; i1 <= nCellIDs.End; ++i1)
            {
                foreach (var c in coarseContact.N_Cells[i1].FineCells)
                {
                    foreach (var ffid in fineContact.GetNZoneCellOFaces(c))
                    {
                        InNCoarseCell[ffid] = i1;
                    }
                }
            }
        }
        private void addContactFaceToStorage()
        {
            IndexRecorder faceIDs = fineContact.GetInnerIndex().FaceIDs;
            for (int i1 = faceIDs.Start; i1 <= faceIDs.End; i1++)
            {
                ONPair onnew = new ONPair(InOCoarseCell[i1], InNCoarseCell[i1]);
                add(i1, onnew);
            }
        }
        void add(int i1, ONPair onnew)
        {
            ref var store =ref contactTempCells[onnew.Owner - tempCellsStart].CoarseOFacesStorage;
            foreach (var f in store)
            {
                if (f.NeighborCellIndex == onnew.Neighbor)
                {
                    f.FineFace_O2N.Add(i1);
                    return;
                }
            }
            MGFaceTemp cfnew = new MGFaceTemp()
            {
                OwnerCellIndex = onnew.Owner,
                NeighborCellIndex = onnew.Neighbor
            };
            cfnew.FineFace_O2N.Add(i1);
            store.Add(cfnew);
        }
        private void splitContactCoarseFaceFromStorage()
        {
            int icount = 0;
            foreach (var c in contactTempCells)
            {
                icount += c.CoarseOFacesStorage.Count;
            }
            MGPair[] Pairs = new MGPair[icount];

            IndexRecorder oCellIDs = coarseContact.O_Index.CellIDs;
            IndexRecorder nCellIDs = coarseContact.N_Index.CellIDs;
            IndexRecorder oFaceIDs = coarseContact.O_Index.FaceIDs;
            IndexRecorder nFaceIDs = coarseContact.N_Index.FaceIDs;
            MGFace[] oFaces = coarseContact.O_Faces;
            MGFace[] nFaces = coarseContact.N_Faces;

            QueueTool_O.Create(oCellIDs.GetCount(), Pairs.Length);
            QueueTool_N.Create(nCellIDs.GetCount(), Pairs.Length);
            {
                int i1 = 0;
                foreach (var c in contactTempCells)
                {
                    foreach (var f in c.CoarseOFacesStorage)
                    {
                        ref MGPair pair = ref Pairs[i1];
                        pair.FinePairs = f.FineFace_O2N.ToArray();
                        pair.O_Cell = f.OwnerCellIndex;
                        pair.O_Face = f.OwnerCellIndex + oFaceIDs.Start - oCellIDs.Start;
                        pair.O_InnCell = oFaces[pair.O_Face].OSideCell;
                        pair.N_Cell = f.NeighborCellIndex;
                        pair.N_Face = f.NeighborCellIndex + nFaceIDs.Start - nCellIDs.Start;
                        pair.N_InnCell = nFaces[pair.N_Face].OSideCell;
                        QueueTool_O.AddOneToQueue(f.OwnerCellIndex - oCellIDs.Start, i1);
                        QueueTool_N.AddOneToQueue(f.NeighborCellIndex - nCellIDs.Start, i1);
                        i1++;
                    }
                }
            }
            MGCell[] cells = coarseContact.O_Cells;
            for (int i1 = oCellIDs.Start; i1 <= oCellIDs.End; ++i1)
            {
                QueueTool_O.ConvertQueueToArray(out cells[i1].OFaces, i1 - oCellIDs.Start);
            }
            cells = coarseContact.N_Cells;
            for (int i1 = nCellIDs.Start; i1 <= nCellIDs.End; ++i1)
            {
                QueueTool_N.ConvertQueueToArray(out cells[i1].OFaces, i1 - nCellIDs.Start);
            }
            coarseContact.Pairs = Pairs;
            coarseContact.InnerIndex = new IndexNumber(0, Pairs.Length - 1, 0, Pairs.Length - 1);
        }

        private void checkTopology()
        {
            MGPair[] pairs = coarseContact.Pairs;
            int indexcount = fineContact.GetInnerIndex().FaceIDs.GetCount();
            int finecount = 0;
            foreach (var f in pairs)
            {
                finecount += f.FinePairs.Length;
            }
            if (indexcount != finecount) Console.WriteLine($"Contact网格数量不一致");
            for (int i1 = coarseContact.O_Index.CellIDs.Start; i1 <= coarseContact.O_Index.CellIDs.End; i1++)
            {
                int[] faces = coarseContact.O_Cells[i1].OFaces;
                foreach (var pid in faces)
                {
                    if (pairs[pid].O_Cell != i1) Console.WriteLine("生成粗网格交界面出错1");
                    if (pairs[pid].O_Face != coarseContact.O_Cells[i1].NFaces[0])
                    {
                        Console.WriteLine($"生成粗网格交界面出错2,cell{i1},pair中ID{pairs[pid].O_Face}Cell中ID{coarseContact.O_Cells[i1].NFaces[0]}");
                        printFace(pairs[pid].O_Face);
                        printFace(coarseContact.O_Cells[i1].NFaces[0]);
                        void printFace(int faceid)
                        {
                            Console.WriteLine($"{faceid} face ,owner {coarseContact.O_Faces[faceid].OSideCell}, neighbor{coarseContact.O_Faces[faceid].NSideCell}");
                        }
                    }
                }
            }
            for (int i1 = coarseContact.N_Index.CellIDs.Start; i1 <= coarseContact.N_Index.CellIDs.End; i1++)
            {
                foreach (var pid in coarseContact.N_Cells[i1].OFaces)
                {
                    if (pairs[pid].N_Cell != i1) Console.WriteLine("生成粗网格交界面出错3");
                    if (pairs[pid].N_Face != coarseContact.N_Cells[i1].NFaces[0]) Console.WriteLine("生成粗网格交界面出错4");
                }
            }
        }
    }
}
//private void reNumberContactInnerFace()
//{
//    MGPair[] Pairs = coarseContact.Pairs;
//    MGFace[] ofaces = coarseContact.O_Faces;
//    MGFace[] nfaces = coarseContact.N_Faces;
//    for (int i1 = 0; i1 < Pairs.Length; i1++)
//    {
//        Pairs[i1].O_InnCell = ofaces[Pairs[i1].O_Face].OSideCell;
//        Pairs[i1].N_InnCell = nfaces[Pairs[i1].N_Face].OSideCell;
//    }
//    //IndexRecorder oCellIDs = coarseContact.O_Index.CellIDs;
//    //IndexRecorder nCellIDs = coarseContact.N_Index.CellIDs;
//    //QueueTool oqu = new QueueTool();
//    //QueueTool nqu = new QueueTool();
//    //oqu.Create(coarseContact.O_Index.CellIDs.GetCount(), Pairs.Length);
//    //nqu.Create(coarseContact.N_Index.CellIDs.GetCount(), Pairs.Length);

//}
//private void completeZoneCell()
//{
//    MGCell[] cells = coarseContact.O_cells;
//    int deltaOId = coarseContact.O_Index.CellIDs.Start;
//    for (int i1 = 0; i1 < OCellsTemp.Length; i1++)
//    {
//        cells[i1 + deltaOId].OFaces = OCellsTemp[i1].CellFacesAsO.ToArray();
//    }
//    cells = coarseContact.N_cells;
//    deltaOId = coarseContact.N_Index.CellIDs.Start;
//    for (int i1 = 0; i1 < NCellsTemp.Length; i1++)
//    {
//        cells[i1 + deltaOId].OFaces = NCellsTemp[i1].CellFacesAsO.ToArray();
//    }

//    //MGCell[] cells = coarseContact.O_cells;
//    //int deltaOId = coarseContact.O_Index.CellIDs.Start;
//    //for (int i1 = 0; i1 < OCellsTemp.Length; i1++)
//    //{
//    //    cells[i1 + deltaOId].OFaces = OCellsTemp[i1].CellFacesAsO.ToArray();
//    //}
//    //cells = coarseContact.N_cells;
//    //deltaOId = coarseContact.N_Index.CellIDs.Start;
//    //for (int i1 = 0; i1 < NCellsTemp.Length; i1++)
//    //{
//    //    cells[i1 + deltaOId].OFaces = NCellsTemp[i1].CellFacesAsO.ToArray();
//    //}
//}
//private void checkTopology()
//{
//    MGContact contact = coarseContact;
//    //1.检查数量
//    int ocount = 0, ncount = 0, pcount = 0;
//    for (int i1 = contact.O_Index.CellIDs.Start; i1 <= contact.O_Index.CellIDs.End; i1++)
//    {
//        ocount += contact.O_cells[i1].OFaces.Length;
//    }
//    for (int i1 = contact.N_Index.CellIDs.Start; i1 <= contact.N_Index.CellIDs.End; i1++)
//    {
//        ncount += contact.N_cells[i1].OFaces.Length;
//    }
//    pcount = contact.Pairs.Length;
//    Console.WriteLine($"contact face o:{ocount} n:{ncount} p:{pcount}");
//    {
//        int i1 = 0;
//        foreach (var p in contact.Pairs)
//        {
//            ref MGCell ocell = ref contact.O_cells[p.O_Cell];
//            if (ocell.NFaces.Length != 1)
//            {
//                Console.WriteLine("长度应为1 error1");
//            }
//            if (p.O_Face != ocell.NFaces[0])
//            {
//                Console.WriteLine("o 不一致 error2");
//            }
//            if (!indexinarray(i1, ocell.OFaces))
//            {
//                Console.WriteLine("error3");
//            }
//            if (p.O_InnCell > contact.O_zone.InnerIndex.CellIDs.End)
//            {
//                Console.WriteLine("error4");
//            }
//            ref MGCell ncell = ref contact.N_cells[p.N_Cell];
//            if (ncell.NFaces.Length != 1)
//            {
//                Console.WriteLine("长度应为1 error5");
//            }
//            if (p.N_Face != ncell.NFaces[0])
//            {
//                Console.WriteLine("n 不一致 error6");
//            }
//            if (!indexinarray(i1, ncell.OFaces))
//            {
//                Console.WriteLine("error3");
//            }
//            if (p.N_InnCell > contact.N_zone.InnerIndex.CellIDs.End)
//            {
//                Console.WriteLine("error4");
//            }
//            i1++;
//        }
//        bool indexinarray(int id, int[] array)
//        {
//            foreach (var i in array)
//            {
//                if (id == i)
//                {
//                    return true;
//                }
//            }
//            return false;
//        }
//    }

//}